package edu.buaa.act.anonymous;

import edu.buaa.act.helper.Utils;
import edu.buaa.act.model.GPSPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by T7810 on 2017/4/23.
 */
public class AnonymousResultReader
{
    private static Logger log = Utils.getDebugLogger();


    public static List<List<GPSPoint>> read(File inputFile, long initTimestamp, int timeIntervalMilliSecond, boolean skipSame) throws IOException
    {
        List<GPSPoint> list = new ArrayList<>();
        BufferedReader ir = new BufferedReader(new FileReader(inputFile));
        String lineTxt;
        String preLat=null,preLon=null;
        long skipCount=0;
        boolean firstLoop=true;
        while((lineTxt = ir.readLine()) != null) {
            String[] arr = lineTxt.split("\t");
            int carID = Integer.parseInt(arr[0]);
            int timeSlot = Integer.parseInt(arr[1]);
            double latitude = Double.parseDouble(arr[2]);
            double longitude = Double.parseDouble(arr[3]);
            if(firstLoop){
                firstLoop=false;
                list.add(new GPSPoint(carID, initTimestamp + timeIntervalMilliSecond * timeSlot, longitude, latitude));
            }else {
                if(arr[2].equals(preLat) && arr[3].equals(preLon) && skipSame){
                    skipCount++;
                }else{
                    list.add(new GPSPoint(carID, initTimestamp + timeIntervalMilliSecond * timeSlot, longitude, latitude));
                }
            }
            preLat = arr[2];
            preLon = arr[3];
        }
        ir.close();
        log.debug("skip {} gps point. current {} points", skipCount, list.size());
        printGeoBoundInfo(list);
        return separateTrajByCarID(list);
    }

    public static List<List<GPSPoint>> readJavaOutput(List<List<GPSPoint>> data, long initTimestamp, int timeIntervalMilliSecond, boolean skipSame)
    {
        List<List<GPSPoint>> result = new ArrayList<>();
        long skipCount = 0;
        for(List<GPSPoint> traj : data){
            GPSPoint last=null;
            List<GPSPoint> newTraj = new ArrayList<>();
            for(int i=0;i<traj.size();i++){
                GPSPoint p = traj.get(i);
                if(i==0){
                    p.setTime(initTimestamp + timeIntervalMilliSecond * p.getTimeSlot());
                    newTraj.add(p);
                }else{
                    if( skipSame &&
                        Math.abs(p.getLat()-last.getLat())<0.0000001 &&
                        Math.abs(p.getLon()-last.getLon())<0.0000001 ){
                        skipCount++;
                    }else{
                        p.setTime(initTimestamp + timeIntervalMilliSecond * p.getTimeSlot());
                        newTraj.add(p);
                    }
                }
                last = p;
            }
            result.add(newTraj);
        }
        log.trace("skip {} points", skipCount);
        return result;
    }

    private static void printGeoBoundInfo(List<GPSPoint> list)
    {
        double minLat=Double.MAX_VALUE;
        double minLon=Double.MAX_VALUE;
        double maxLat=Double.MIN_VALUE;
        double maxLon=Double.MIN_VALUE;
        for(GPSPoint p : list){
            double lat = p.getLatitude();
            double lon = p.getLongitude();
            if(lat<minLat) minLat = lat;
            if(lat>maxLat) maxLat = lat;
            if(lon<minLon) minLon = lon;
            if(lon>maxLon) maxLon = lon;
        }
        log.debug("Geo bound after anonymous: ({}, {}, {}, {})", minLat, maxLat, minLon, maxLon);
    }

    // same as RawDataCleaning.separateTrajByCarID(), but asc rather than dec
    private static List<List<GPSPoint>> separateTrajByCarID(List<GPSPoint> rawData)
    {
        List<List<GPSPoint>> result = new ArrayList<>();
        List<GPSPoint> oneCarTraj = null;
        long lastCar=-1;
        for(int i=0; i<rawData.size(); i++){
            GPSPoint p = rawData.get(i);
            if(i==0){
                lastCar = p.getCarID();
                oneCarTraj = new ArrayList<>();
                oneCarTraj.add(p);
                result.add(oneCarTraj);
            }else{
                long car = p.getCarID();
                if(car==lastCar){
                    oneCarTraj.add(p);
                }else{
                    oneCarTraj = new ArrayList<>();
                    oneCarTraj.add(p);
                    result.add(oneCarTraj);
                }
                lastCar = car;
            }
        }
        log.debug("contains {} car's trajectories.",result.size());
        return result;
    }



}
